package com.dmg.sp.config;


import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.dmg.sp.dao.MenuMapper;
import com.dmg.sp.entity.Menu;
import com.dmg.sp.service.MenuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.UnanimousBased;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.expression.WebExpressionVoter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@EnableWebSecurity
@Slf4j
@Configuration
public class SpConfig {

    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Autowired
    private MyAuthenticationEntryPoint myAuthenticationEntryPoint;

    @Autowired
    private MenuMapper menuMapper;


    //密码加密
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    //安全过滤器链
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        //采用ant语法规则的匹配器
        AntPathMatcher antPathMatcher=new AntPathMatcher();
        //每次都需要认证 不需要session 会话管理策略设置为无状态，这样就可以防止应用程序的会话被劫持攻击。
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http
                //禁用表单登录 前后分离用不上
                .formLogin().disable()
                //先进行jwt 校验 在进行账号密码登录
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                 //动态拦截所有请求 如果没有匹配上的 那么就拦截
                .authorizeHttpRequests(x->x.anyRequest().authenticated())
                //没有登录 直接返回异常信息
                .exceptionHandling(x->x.authenticationEntryPoint(myAuthenticationEntryPoint))
                //关闭csrf
                .csrf().disable();
        //创建对象
        return http.build();
    }


    //忽略路径 放行路径
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer(){
        //放行登录接口 这样才能登录成功
        return x->x.ignoring().requestMatchers("/dengLu");
    }


    /**
     * 把认证管理器注入到容器
     * LoginServiceImpl类中 才能使用这个认证接口
     * @param config
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
        return config.getAuthenticationManager();
    }

}
